package com.scaffold.commons;

import java.io.Serializable;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicLong;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.type.Type;

/**
 * 自定义主键生成器
 * @author wangjg
 *
 */
public class MyIdGenerator implements IdentifierGenerator, Configurable {
	private AtomicLong nextValue = new AtomicLong(1L);
	private long maxValue = Long.MAX_VALUE;
	private int version = 0;
	private int count = 10;
	private Loader provider;
	
	//TODO 
	private synchronized Long loadNextValue(int currentVersion){
		if(currentVersion!=this.version){
			return nextValue.getAndIncrement();
		}
		Long startValue = provider.load(count);
		this.nextValue.set(startValue);
		this.maxValue = startValue+count-1;
		this.version ++;
		return nextValue.getAndIncrement();
	}
	
	@Override
	public void configure(Type type, Properties params, Dialect dialect)
			throws MappingException {
		
	}

	@Override
	public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
		Long newId = nextValue.getAndIncrement();
		while(newId>maxValue){
			newId = this.loadNextValue(this.version);
		}
		return newId;
	}

	static interface Loader{
		public Long load(int count);
	}
}
/*
配置:
	<id name="id" type="long" column="id" > 
		<generator class="hibernate.IncrementGenerator" /> 
	</id>
注解:
	@Id
	@GeneratedValue(generator = "myIdGen")
	@GenericGenerator(name = "myIdGen", strategy = "com.scaffold.commons.MyIdGenerator")
 */